package net.xumf.support.aop;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import net.xumf.support.annotation.RequiresRoles;
import net.xumf.support.auth.VerificationUtil;
import net.xumf.support.enums.CodeEnum;
import net.xumf.support.enums.Logical;
import net.xumf.support.exception.SystemException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Pointcut;

import java.lang.reflect.Method;

@Slf4j
public class AuthRoles {

    @Pointcut("@annotation(net.xumf.support.annotation.RequiresRoles)")
    public void pointcut() {
    }

    @After("pointcut()")
    public void doAfter(JoinPoint joinPoint) {
        try {
            this.auth(joinPoint);
        } catch (final Exception e) {
            log.error("异常信息:{}", e);
        }
    }

    @AfterThrowing(pointcut = "pointcut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        try {
            this.auth(joinPoint);
        } catch (final Exception ex) {
            log.error("异常信息:{}", ex.getMessage());
        }
    }

    public void auth(JoinPoint joinPoint) throws ClassNotFoundException {
        final String targetName = joinPoint.getTarget().getClass().getName();
        final String methodName = joinPoint.getSignature().getName();
        final Object[] arguments = joinPoint.getArgs();
        final Class targetClass = Class.forName(targetName);
        final Method[] methods = targetClass.getMethods();
        for (final Method method : methods) {
            if (method.getName().equals(methodName)) {
                final Class[] methodParameterTypes = method.getParameterTypes();
                if (methodParameterTypes.length == arguments.length) {
                    RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class);
                    boolean b;
                    if (Logical.AND == requiresRoles.logical()) {
                        b = VerificationUtil.getInstance().hasRoleAnd(Lists.newArrayList(requiresRoles.value()));
                    } else {
                        b = VerificationUtil.getInstance().hasRoleOr(Lists.newArrayList(requiresRoles.value()));
                    }
                    if (!b) {
                        throw new SystemException(CodeEnum.NOT_AUTH);
                    }
                    break;
                }
            }
        }
    }

}
